export function patch(oldVnode, vnode) {
    const isRealElement = oldVnode.nodeType;
    if(isRealElement) {
        const oldElm = oldVnode;
        const parentNode = oldElm.parentNode;
        let el = createElm(vnode);
        parentNode.insertBefore(el, oldElm.nextSibling);
        parentNode.removeChild(oldElm);
        return el;
    } else {
        // diff算法
        if(oldVnode.tag !== vnode.tag) {
            // 新旧标签不一致
            oldVnode.el.parentNode.replaceChild(createElm(vnode), oldVnode.el);
        }
        // 如果旧节点是一个文本节点
        if(!oldVnode.tag) {
            if(oldVnode.text !== vnode.next) {
                oldVnode.el.textContent = vnode.text;
            }
        }
        // 以上情况都不符，则代表标签一致，直接复用
        const el = (vnode.el = oldVnode.el);
        updateProperties(vnode, oldVnode.data);
        const oldCh = oldVnode.children || [];
        const newCh = vnode.children || [];
        if(oldCh.length > 0 && newCh.length > 0) {
            updateChildren(el, oldCh, newCh);
        } else if(oldCh.length) {
            el.innerHTML = '';
        } else if(newCh.length) {
            for(let i =0; i < newCh.length; i++) {
                const child = newCh[i];
                el.appendChild(createElm(child));
            }
        }
    }
}

function createElm(vnode) {
    let {tag, data, children, text} = vnode;
    if(typeof tag === 'string') {
        vnode.el = document.createElement(tag);
        updateProperties(vnode);
        children.forEach(child => {
            vnode.el.appendChild(createElm(child));
        })
    } else {
        vnode.el = document.createTextNode(text);
    }
    return vnode.el;
}

function updateProperties(vnode, oldProps = {}) {
    let newProps = vnode.data || {};
    let el = vnode.el;
    // 如果新节点无属性，直接删除老节点的属性
    for(const k in oldProps) {
        if(!newProps[k]) {
            el.removeAttribute(k);
        }
    }
    // 特殊处理 style
    for(let key in newProps) {
        if(key === 'style') {
            for(let styleName in newProps.style) {
                el.style[styleName] = newProps.style[styleName];
            }
        } else if(key === 'class') {
            el.className = newProps.class;
        } else {
            el.setAttribute(key, newProps[key]);
        }
    }
}